Wer einen genauen Frequenzzähler zur Verfügung hat, kann die Gangabweichung unter Kontrolle bringen:
Aber wie erreicht man eine Genauigkeit von 10-6 bei lauter
8-bit-Teilern?
Irgendwelche Fummeleien mit umschaltenden Teilern sehen nicht gerade
elegant aus...
Die Lösung ist ein genügend breiter Überlauf-Zähler. Wie funktioniert das?
Damit wird ein 5-Bit-Zähler simuliert.... dec r18 ;r18 sei der ISR-Teiler brne ende ldi r18, 32 call SekundeVergangen ende :...
... ldi r16, 8 add r18,r16 ;r18 sei der ISR-Akkumulator brcc ende call SekundeVergangen ende :...
Tint = 1024 * 256 / fosz, fosz = 8000000 HzErwischt! Mit Zeiten rechnen ist einfacher!
Tint = 1024 * 256 * Tosz, Tosz = 125 nsDie Zeit beträgt in diesem Falle:
0,032768 sAlso eine Zahl, die kleiner als Eins (eine Sekunde) ist, und das ist gut so!
Dazu ermitteln wir einen (endlichen) Bruch, in dessen Nenner die computerfreundliche Zahl 232 steht, wir erweitern also um 232:
Tint = 1024 * 256 * Tosz * 232 / 232Und fortan nehmen wir davon nur den (gerundeten) Zähler. Der ist eine riesige Ganzzahl und beträgt hier:
140737488 - hexadezimal 0x08637BD0Noch einmal: Das ist der Zähler für den Binärbruch, in dessen Nenner 232 steht. Damit erreichen wir eine Auflösung von 1/140737488, also unter 10-8. Eine Uhr hätte damit eine Gangabweichung von 1 Sekunde in 4 Jahren. Das ist mit einem nicht temperaturstabilisierten Quarz, noch dazu am simplen Mikrocontroller, absolut illusorisch. 3 Bytes reichen auch: 1/(0x08637B+1) (Rundung) ergibt 1,8*10-6, 1 Sekunde in 6 Tagen.
Und was macht man nun damit?
Diese Konstante wird bei jedem Interrupt auf einen 4-Byte-Akkumulator addiert;
bei jedem Ăśberlauf ist eine Sekunde vergangen!
Dieser 4-Byte-Akkumulator beinhaltet die »Nachkomma-
In Atmel-Worten:
Und das ist alles, was von der grauen Theorie ĂĽbrig bleibt!.dseg VierByteAkku :.byte 4 .cseg Timer0ISR :push r16 in r16,sreg push r16 push xl ;xh sei stillschweigend stets Null push r4 ldi xl,VierByteAkku ld r4,x ldi r16,$D0 ;letztes Byte add r4,r16 st x+,r4 ld r4,x ; das schreit ldi r16,$7B ; nach adc r4,r16 ; einem st x+,r4 ; Makro ld r4,x ldi r16,$63 adc r4,r16 st x+,r4 ld r4,x ldi r16,$08 ;erstes Byte adc r4,r16 st x+,r4 pop r4 pop xl jnc ende call SekundeVergangen ende : pop r16out sreg,r16 pop r16 reti
Exakt gleich lange Sekunden können nur mit einem gezogenen Quarz erreicht werden.
Andererseits darf SekundeVergangen auch die Interrupts freigeben;
darf dann allerdings nicht mehr als eine knappe Sekunde verbrauchen,
alles bei voller sonstiger Interruptlast.
Andernfalls kommt es zur Reentranz (= ungewollte Rekursion).
Dagegen helfen selbstgebastelte Semaphoren (siehe anderes Kapitel).
Ein Uhrenvergleich mit einer Funkuhr ist ein sehr langwieriges Unterfangen und sollte nur im Notfall nach guter Vorbereitung erfolgen. Als Messzeit sollte man 24 Stunden einplanen.
Die Quarzfrequenz darf keinesfalls direkt am Quarz gemessen werden, weil die Tastspitze mit ihrer (kapazitiven) Last unweigerlich den Quarz wegzieht.
Schreiben Sie in Ihre ISR Kode hinein, das ein Ausgabepin hin- und her schaltet (toggelt, halbe Frequenz beachten!) oder pulst.
Oder aber, geben Sie im Sekundentakt einen Puls aus. Hierbei ist der Jitter ist für das Kalibrieren katastrophal, deshalb benutzt man zunächst einen »geraden« Wert für die Konstante, bspw. 0x08000000.
Die Quarz-Periodendauer ergibt sich dann einfach zu:
Tosz = Tgemessen / Vorteiler / 256 ( / 32 fĂĽr Sekundentakt)Notieren Sie dabei die Temperatur der Schaltung.
Für eine Kennlinie brauchen Sie einen Gefrierschrank und einen Ofen, um für jede Temperatur (bspw. alle 5 °C) die Oszillatorperiodendauer zu messen.